@tool
extends StaticBody3D
class_name BasicBlock

const _base_texture_folder = "res://addons/devblocks/textures/"

## 颜色分组
enum DEVBLOCK_COLOR_GROUP {
	## 深色组，包括深灰、深蓝等较暗的颜色，适用于阴影或夜晚场景。
	DARK,
	## 绿色组，包括各种绿色调，适用于自然环境如草地、森林等。
	GREEN,
	## 浅色组，包括浅灰、米白等浅色调，适用于高光区域和日间场景。
	LIGHT,
	## 橙色组，包括橙色及其相关色调，适用于落日或秋季主题。
	ORANGE,
	## 紫色组，包括各种紫色调，适用于神秘或科幻主题。
	PURPLE,
	## 红色组，包括各种红色调，适用于危险、警示或热情主题。
	RED
};
const _devblock_color_to_foldername := [
	"dark",
	"green",
	"light",
	"orange",
	"purple",
	"red"
]
# Looks very bad, eh


## 样式
enum DEVBLOCK_STYLE {
	## 默认样式，没有特殊装饰或图案。
	DEFAULT,
	## 交叉样式，设计中包含十字交叉图案，适用于标志性地面或墙面。
	CROSS,
	## 对比样式，使用鲜明对比的颜色或材质，用于突出重要的游戏元素。
	CONTRAST,
	## 对角线样式，包含一个或多个对角线图案，适合引导玩家视线或路径。
	DIAGONAL,
	## 渐变对角线样式，对角线图案带有渐变效果，适用于创建动态视觉效果。
	DIAGONAL_FADED,
	## 组合交叉样式，多个小交叉组成的复杂图案，适用于详细装饰。
	GROUPED_CROSS,
	## 组合棋盘样式，棋盘格局更加复杂或有规律的变化，用于增加视觉复杂度。
	GROUPED_CHECKERS,
	## 棋盘样式，简单的黑白或其他两种颜色交替的格子，常用于地板或背景。
	CHECKERS,
	## 交叉棋盘样式，棋盘格与交叉图案的结合，用于创造独特的视觉层次感。
	CROSS_CHECKERS,
	## 楼梯样式，用于明确表示可以走动的楼梯区域，具有引导性功能。
	STAIRS,
	## 门样式，标记出通道或门的位置，方便玩家识别。
	DOOR,
	## 窗户样式，表示墙面上的窗户部分，通常用于增加环境的真实感。
	WINDOW,
	## 信息样式，用于显示提示或游戏信息的特殊区域，如教学或任务提示。
	INFO
};

@onready var _mesh : MeshInstance3D = $Mesh
## 颜色分组
@export var block_color_group : DEVBLOCK_COLOR_GROUP = DEVBLOCK_COLOR_GROUP.DARK :
	set(value):
		block_color_group = value
		_update_mesh()
## 风格
@export var block_style : DEVBLOCK_STYLE = DEVBLOCK_STYLE.DEFAULT :
	set(value):
		block_style = value
		_update_mesh()

signal transform_changed

func _ready():
	_mesh.set_surface_override_material(0, load("res://addons/devblocks/blocks/block_material.tres").duplicate(true))
	_update_mesh()
	_update_uvs()
	_mesh.set_notify_local_transform(true)
	transform_changed.connect(Callable(self, "_update_uvs"))

func _notification(what : int):
	if what == NOTIFICATION_TRANSFORM_CHANGED:
		transform_changed.emit()

func _update_mesh() -> void:
	if not _mesh:
		return
	var mat := _mesh.get_surface_override_material(0)
	if not mat:
		return
		
	var texture_i : int = block_style + 1
	var texture_i_str : String = ("0" if texture_i < 10 else "") + str(texture_i)
	var texture_name := "texture_" + texture_i_str
	var texture_folder :String = _devblock_color_to_foldername[block_color_group]
	var full_texture_path :String = _base_texture_folder + texture_folder + "/" + texture_name + ".png"
	var texture : Resource = load(full_texture_path)
	if not (texture is Texture):
		return
	
	_mesh.get_surface_override_material(0).set("albedo_texture", texture as Texture)

func _update_uvs() -> void:
	var mat = _mesh.get_surface_override_material(0)
	var offset := Vector3()
	for i in range(3):
		var different_offset := fmod(scale[i], 2.0) >= 0.99
		var different_offset2 := fmod(scale[i], 1.0) >= 0.49
		offset[i] = (0.5 if different_offset else 1) - (0.25 if different_offset2 else 0.0)
	mat.set("uv1_scale", scale)
	mat.set("uv1_offset", offset)
